import React, { useMemo } from 'react';
import { message, Tag, Input } from 'antd';
import { customUpload } from '@/utils/fileUpload';
import BraftEditor from 'braft-editor';
import _ from 'lodash';
import { ContentUtils } from 'braft-utils';
import { useRequest } from '@/hooks';
import { useMount } from 'react-use';
import { getRecruitParam } from '../../service';
import { TEMPLATE_CODE } from '../../constants';

const formatInitialValue = (str, insertParamList) => {
    if (!str) {
        return '';
    }
    let tempStr = str;
    const arr = str.match(/\${[a-zA-z]+}/g);
    if (arr && arr.length > 0) {
        arr.forEach(item => {
            const field = item.replace('${', '').replace('}', '');
            if (
                field === 'recruitmentFeedbackButton' ||
                field === 'offerFeedbackEntranceButton' ||
                field === 'jobSubmitLinkButton' ||
                field === 'backgroundFeedBackButton'
            ) {
                return;
            }
            const fieldName = insertParamList.find(c => c.field === field)?.value || '';
            tempStr = tempStr.replace(item, `<span data-foo="${field}" class="column-item">${fieldName}</span>`);
        });
    }
    return tempStr;
};

// 插入参数的参数列表
const MyComponent = ({ dataSource = [], onClick, ...restProps }) => {
    const [queryDataSource, setQueryDataSource] = React.useState(null);
    const [keyWord, setKeyWord] = React.useState('');
    const liStyle = {
        backgroundColor: 'hsla(0,0%,100%,.1)',
        borderRadius: 2,
        margin: 5,
        color: '#fff',
        fontSize: 12,
        minHeight: 30,
        lineHeight: '30px',
        textAlign: 'center',
        cursor: 'pointer'
    };

    const computedWidth = useMemo(() => {
        let maxLength = 0;
        dataSource.forEach(item => {
            if (item.value.length > maxLength) {
                maxLength = item.value.length;
            }
        });
        return `${maxLength + 2}em`;
    }, [dataSource]);

    const ulStyle = {
        width: computedWidth,
        maxHeight: 260,
        overflow: 'auto',
        scrollbarWidth: 'thin' // firefox 专属属性
    };

    // 参数关键词搜索
    const queryKeyWord = _.debounce(value => {
        setKeyWord(value);
        const newData = dataSource.filter(e => e?.value?.indexOf(value) !== -1);
        setQueryDataSource(newData);
    }, 300);

    const highlightSearch = word => {
        const data = word; //   获取文本
        const newData = data.split(keyWord); //  通过关键字的位置开始截取，结果为一个数组
        const len = newData.length;
        return (
            <text>
                {newData.map((item, index) => (
                    <text>
                        {item}
                        <text style={{ color: '#ff9500' }}>{index === len - 1 ? '' : keyWord}</text>
                    </text>
                ))}
            </text>
        );
    };

    return (
        <ul style={ulStyle} {...restProps}>
            <div style={{ padding: '5px 5px 0' }}>
                <Input placeholder="输入关键字" allowClear onChange={e => queryKeyWord(e.target.value)} />
            </div>
            {(queryDataSource || dataSource)?.map(item => (
                <li
                    style={liStyle}
                    key={item.field}
                    onClick={() => {
                        if (onClick) {
                            onClick(item);
                        }
                    }}
                >
                    {highlightSearch(item.value)}
                </li>
            ))}
        </ul>
    );
};

let editorId = 1;

/**
 * 邮件模板编辑器
 */
const BraftTemplate = ({ type, initialValue, onChange, readOnly, ...restProps }) => {
    const dropDownInstance = React.useRef(null);
    const idRef = React.useRef(0);
    const editorRef = React.useRef(
        BraftEditor.createEditorState(null, {
            editorId: `editor-with-entity-extension-${editorId}`
        })
    );
    const [editorValue, setEditorValue] = React.useState(editorRef.current);

    // 获取插入参数列表
    const { data: insertParamList } = useRequest(() => getRecruitParam(TEMPLATE_CODE[type]), {
        initialData: undefined,
        formatResult: result => {
            const { code, data, msg } = result;
            if (code === 10000) {
                const { paramValue } = data;
                try {
                    return JSON.parse(paramValue);
                } catch (error) {
                    return [];
                }
            }
            message.error(msg);
            return [];
        }
    });

    useMount(() => {
        const entityExtension = {
            // 指定扩展类型
            type: 'entity',
            // 指定该扩展对哪些编辑器生效，不指定includeEditors则对所有编辑器生效
            includeEditors: [`editor-with-entity-extension-${editorId}`],
            // 指定扩展的entity名称，推荐使用全部大写，内部也会将小写转换为大写
            name: 'COLUMN-ITEM',
            // 在编辑器工具栏中增加一个控制按钮，点击时会将所选文字转换为该entity
            // control: {
            //     text: '按键'
            // },
            // 指定entity的mutability属性，可选值为MUTABLE和IMMUTABLE，表明该entity是否可编辑，默认为MUTABLE
            mutability: 'IMMUTABLE',
            // 指定通过上面新增的按钮创建entity时的默认附加数据
            // data: {
            //     foo: ''
            // },
            // 指定entity在编辑器中的渲染组件
            component: props => {
                const entity = props.contentState.getEntity(props.entityKey);
                const { foo, id } = entity.getData();
                const handleRemove = () => {
                    const childrenText = props.children?.[0]?.props?.text || '';
                    const html = editorRef.current
                        .toHTML()
                        .replace(
                            `<span data-foo="${foo}" data-id="${id}" class="column-item">${childrenText}</span>`,
                            ''
                        );
                    const obj = BraftEditor.createEditorState(html, {
                        editorId: `editor-with-entity-extension-${editorId}`
                    });
                    setEditorValue(obj);
                };
                return (
                    <Tag
                        key={id}
                        closable={!readOnly}
                        style={{
                            paddingTop: 4,
                            paddingBottom: 4,
                            marginLeft: 4,
                            marginRight: 4,
                            marginBottom: 4,
                            textIndent: 0,
                            background: '#F0F7FF',
                            border: '1px solid #F0F7FF'
                        }}
                        onClose={() => handleRemove()}
                    >
                        {props.children}
                    </Tag>
                );
            },
            // 指定html转换为editorState时，何种规则的内容将会转换成该entity
            // eslint-disable-next-line consistent-return
            importer: (nodeName, node) => {
                // source属性表明输入来源，可能值为create、paste或undefined
                if (nodeName.toLowerCase() === 'span' && node.classList && node.classList.contains('column-item')) {
                    // 此处可以返回true或者一个包含mutability和data属性的对象
                    let tempId = 0;
                    if (node.dataset.id) {
                        tempId = node.dataset.id;
                    } else {
                        idRef.current += 1;
                        tempId = idRef.current;
                    }
                    return {
                        mutability: 'IMMUTABLE',
                        data: {
                            id: tempId,
                            foo: node.dataset.foo
                        }
                    };
                }
            },
            // 指定输出该entnty在输出的html中的呈现方式
            exporter: (entityObject, originalText) => {
                // 注意此处的entityObject并不是一个entity实例，而是一个包含type、mutability和data属性的对象
                const { foo, id } = entityObject.data;
                return (
                    <span data-foo={foo} data-id={id} className="column-item">
                        {originalText}
                    </span>
                );
            }
        };

        // 加载扩展模块
        BraftEditor.use(entityExtension);
    });

    // 插入参数
    const handleInsert = column => {
        let content = '';
        // 特殊参数的预处理
        if (
            column?.field === 'recruitmentFeedbackButton' ||
            column?.field === 'offerFeedbackEntranceButton' ||
            column?.field === 'jobSubmitLinkButton' ||
            column?.field === 'backgroundFeedBackButton'
        ) {
            const title = {
                recruitmentFeedbackButton: '马上确认面试安排',
                offerFeedbackEntranceButton: '马上确认录用',
                jobSubmitLinkButton: '提交作业',
                backgroundFeedBackButton: '反馈背调结果'
            };
            // 插入特殊格式化的文字
            content = `<span style="font-size:24px;"><a href="\${${column?.field}}" target="_blank">&gt;&gt;${
                title[column?.field]
            }</a></span>`;
        } else {
            // 插入参数占位符
            content = `<span class="column-item" data-foo="${column?.field}">${column?.value}</span>`;
        }
        const obj = ContentUtils.insertHTML(editorRef.current, content);
        setEditorValue(obj);
        dropDownInstance.current.hide();
    };

    // 报错提示
    const handleEditorChange = editorState => {
        setEditorValue(editorState);
        const html = editorState.toHTML();
        // console.log(html);
        // 内容校验
        if (html.length > 20000) {
            message.error('邮件内容过多');
        }
    };

    // 不允许添加尺寸大于10M的文件
    const myValidateFn = file => {
        if (file.size > 1024 * 1024 * 10) {
            message.error('图片不能大于10M！');
            return false;
        }
        return true;
    };

    // 自定义上传的方法
    const myUploadFn = param => {
        const onSuccess = (response, file) =>
            param.success({
                url: response.data[0].url,
                meta: {
                    id: file.name,
                    title: file.name,
                    alt: file.name
                }
            });
        customUpload({ files: param, onSuccess });
    };

    React.useEffect(() => {
        editorRef.current = editorValue;
        if (onChange) {
            onChange(editorValue.toHTML());
        }
    }, [editorValue, onChange]);

    React.useEffect(() => {
        if (insertParamList) {
            setEditorValue(
                BraftEditor.createEditorState(formatInitialValue(initialValue, insertParamList), {
                    editorId: `editor-with-entity-extension-${editorId}`
                })
            );
        }
    }, [initialValue, insertParamList]);

    React.useEffect(
        () => () => {
            idRef.current = 0;
            editorId += 1;
        },
        []
    );

    const controls = [
        'undo',
        'redo',
        'separator',
        'font-size',
        'line-height',
        'letter-spacing',
        'separator',
        'text-color',
        'bold',
        'italic',
        'underline',
        'strike-through',
        'separator',
        'superscript',
        'subscript',
        'remove-styles',
        'emoji',
        'separator',
        'text-indent',
        'text-align',
        'separator',
        'headings',
        'list-ul',
        'list-ol',
        'blockquote',
        'code',
        'separator',
        'media',
        'link',
        'hr',
        'separator',
        'clear',
        {
            key: 'my-dropdown',
            type: 'dropdown',
            title: '插入参数',
            className: 'my-dropdown',
            html: null,
            text: '插入参数',
            showArrow: true,
            arrowActive: false,
            autoHide: true,
            ref: instance => {
                dropDownInstance.current = instance;
                return dropDownInstance.current;
            },
            component: <MyComponent dataSource={insertParamList} onClick={handleInsert} />
        }
    ];

    return (
        <BraftEditor
            id={`editor-with-entity-extension-${editorId}`}
            controls={controls}
            value={editorValue}
            onChange={handleEditorChange}
            media={{
                uploadFn: myUploadFn,
                validateFn: myValidateFn,
                accepts: {
                    image: 'image/png,image/jpeg,image/gif'
                }
            }}
            placeholder="请输入邮件内容"
            excludeControls={['fullscreen']}
            imageControls={[
                {
                    onClick: block => {
                        console.log(block);
                    }
                },
                'align-left',
                'align-center',
                'align-right',
                'size',
                'remove'
            ]}
            contentStyle={{ height: 600 }}
            readOnly={readOnly}
            {...restProps}
        />
    );
};

export default BraftTemplate;
